% Ejercicio 1 
% valor (−X) que enumera todos los posibles valores de una celda.
valor( mina ).
valor( 0 ).
valor( 1 ).
valor( 2 ).
valor( 3 ).
valor( 4 ).
valor( 5 ).
valor( 6 ).
valor( 7 ).
valor( 8 ).




% Ejercicio 2
% dim(+T,−Cols,−Fils) que es verdadero cuando Cols y Fils correspoden al tamaño del tablero T. Nota: asumir que T es un tablero bien formado, o sea que todas sus filas tiene el  mismo tamaño.
longitud([], 0).
longitud([_|XS], Z):- longitud(XS, Y), Z is Y+1.

dim([]      , 0 , 0).
dim([XS|XSS], C , F) :- length(XS, C), length(XSS, Fm1), F is Fm1+1.





%Ejercicio 3
%pos(+T, −C, −F) que enumera todas las posibles posiciones del tablero. Las casillas se enumeran desde 1 en adelante.
entre(X, Y, X) :- X =< Y.
entre(X, Y, Z) :- X < Y, N is X+1, entre(N, Y, Z).

pos(T, C, F) :-  dim(T, Columnas, Filas), between(1, Filas, F), between(1, Columnas, C).





%Ejercicio 4
%nonvars(?L, −R) que es verdadero cuando R resulta de excluir todos los elementos no instanciados de L.
nonvars([],[]).
nonvars([L|LS],[L|RS]) :- nonvar(L), nonvars(LS, RS), !.
nonvars([L|LS],RS) :- var(L), nonvars(LS, RS), !.
%Para cortar la ejecucion y de esa manera no seguir explorando soluciones, cuando sabiamos que no habría más, agregamos un cut ! . 





%Ejercicio 5
%cant minas(?L, −N) que es verdadero cuando N corresponde a la cantidad de elementos
%instaciados de L que son mina. Notar que L puede tener elementos no instanciados.

mina(A) :- nonvar(A), A=mina.
%Obs: no usamos nonvars porque asi es mas eficiente (recorremos una sola vez)
cant_minas([], 0).
cant_minas([A|AS], CANT):-  mina(A), cant_minas(AS, Z), CANT is Z+1, !.
cant_minas([A|AS], CANT):-  not(mina(A)), cant_minas(AS, CANT), !.













%Ejercicio 6
%vecinos(+T, +C, +F, −L) que es verdadero cuando L corresponde a los vecinos de la celda
%de posición C, F en el tablero T.

vecinos(FS, Columna, Fila, VS) :- filas3(FS,Fila,F1,F2,F3), index3(F1,Columna,V1), index2(F2,Columna,V2), index3(F3,Columna,V3), append(V1,V2,V1V2), append(V1V2,V3,VS), !.
%vecinosyYo tambien "devuelve" el elemento pedido para mejorar la eficiencia en algunos predicados
vecinosyYo(FS, Columna, Fila, VS, Yo) :- filas3(FS,Fila,F1,F2,F3), index3(F1,Columna,V1), index2Yo(F2,Columna,V2,Yo), index3(F3,Columna,V3), append(V1,V2,V1V2), append(V1V2,V3,VS), !.

%index(+L, +Pos, ?Elemento) instancia Elemento en el elemento de la posicion Pos
index([E|_] , 1, E) :- !.
index([_|ES], P, E) :- P1 is P-1, index(ES, P1, E), !.

%index3(+L, +Pos, -[Elemento]) "devuelve" una lista con los elementos en la posicion Pos-1, Pos, Pos+1 (de existir)
index3(_     , P, []):- P<0, !.
index3([]    , 0, []):- !.
index3([E|_] , 0, [E]):- !.
index3([]    , 1, []):- !.
index3([E|ES], 1, [E|RS]) :- index3(ES,0,RS), !.
index3([]    , 2, []):- !.
index3([E|ES], 2, [E|RS]) :- index3(ES,1,RS), !.
index3([]    , P, []) :- P>2, !.
index3([_|ES], P, RS) :- P>2, Pm1 is P-1, index3(ES, Pm1, RS), !.

%index2(+L, +Pos, -[Elemento]) "devuelve" los elementos en la posicion Pos-1, Pos+1 (de existir)
index2(_     , P, []):- P<0, !.
index2([]    , 0, []):- !.
index2([E|_] , 0, [E]):- !.
index2([]    , 1, []):- !.
index2([_|ES], 1, RS) :- index2(ES,0,RS), !.
index2([]    , 2, []):- !.
index2([E|ES], 2, [E|RS]) :- index2(ES,1,RS), !.
index2([]    , P, []) :- P>2, !.
index2([_|ES], P, RS) :- P>2, Pm1 is P-1, index2(ES, Pm1, RS), !.

%index2Yo(+L, +Pos, -[Elemento], -Yo) "devuelve" los elementos en la posicion Pos-1, Pos+1 (de existir), y Yo es el elemento en Pos
index2Yo(_     , P, [], _):- P<0, !.
index2Yo([]    , 0, [], _):- !.
index2Yo([E|_] , 0, [E], _):- !.
index2Yo([]    , 1, [], _):- !.
index2Yo([Yo|ES], 1, RS, Yo) :- index2Yo(ES,0,RS,Yo), !.
index2Yo([]    , 2, [], _):- !.
index2Yo([E|ES], 2, [E|RS],Yo) :- index2Yo(ES,1,RS,Yo), !.
index2Yo([]    , P, [],_ ) :- P>2, !.
index2Yo([_|ES], P, RS,Yo) :- P>2, Pm1 is P-1, index2Yo(ES, Pm1, RS,Yo), !.

%filas3(+T,+F,-F1,-F2,-F3) Instancia F1 F2 F3 en las Filas nro F-1, F, F+1. Si alguna no existe instancia una lista vacia.
filas3(_     ,P,[],[],[]):- P<0, !.
filas3([]    ,0,_ ,_ ,[]):- !.
filas3([F|_] ,0,_ ,_ ,F ):- !.
filas3([]    ,1,_ ,[],[]):- !.
filas3([F|FS],1,F1,F ,F3) :- not(var(F1)),        filas3(FS,0,F1,F,F3), !.
filas3([F|FS],1,F1,F ,F3) :-     var(F1) , F1=[], filas3(FS,0,F1,F,F3), !.
filas3([]    ,2,[],[],[]):- !.
filas3([F|FS],2,F ,F2,F3) :- filas3(FS,1,F,F2,F3), !.
filas3([]    ,Fila,[],[],[]) :- Fila>2, !.
filas3([_|FS],Fila,F1,F2,F3) :- Fila>2, Fm1 is Fila-1, filas3(FS,Fm1,F1,F2,F3), !.

%Escribimos estas funciones (index3, index2, index2Yo, filas3) para mejorar la eficiencia de vecinos, pero se puede usar index para acceder a cada elemento por separado.
%Es mas eficiente porque recorre la lista una sola vez para recuperar 2 o 3 elementos



%Ejercicio 7
%consistente(+T, +C, +F) que es verdadero si la celda en la posicion C, F contiene un
%valor consistente con sus vecinos. O sea, si no es una mina, entonces contiene el número de cuántas minas hay en su vecindad. Se asume que la vecindad y la posición en cuestión están instanciadas.
consistente(T,C,F) :- vecinosyYo(T,C,F,VS,CF), consistente2(VS,CF), !.
consistente2(_,mina):- !.
consistente2(VS,CF) :- not(mina(CF)), cant_minas(VS,CF), !.

%Usamos el predicado vencinosyYo - definida en el ejercicio 6 - para testear cosistencia con mis celdas vecinas



%Ejercicio 8
%consistente (+T) analoga a la anterior pero para todo el tablero.
consistente(T) :- dim(T,C,F), consistenteEn(T,C,F,C).
consistenteEn(T,1,1,_) :- consistente(T,1,1), !.
consistenteEn(T,1,F,W) :- F>1, consistente(T,1,F), Fm1 is F-1, consistenteEn(T,W,Fm1,W), !.
consistenteEn(T,C,F,W) :- C>1, consistente(T,C,F), Cm1 is C-1, consistenteEn(T,Cm1,F,W), !.
%Usamos el mismo predicado pero "recorriendo" todo el tablero












%Toma 1
%Ejercicio 9
%completarA(?T) que enumera todas las posibles soluciones para problema representado por dicho tablero.
%Se busca hacer una implementación simple que complete las celdas del tablero  con alguno de los valores posibles y al final se verifique si es una solución válida. En el archivo base cuentan con ejemplos de tablero y algunos que les permiten mostrar los tableros y cu ́nto tiempo se demora en encontrar una solución.
completarA(T):- instanciar(T), consistente(T).
instanciar([]):-!.
instanciar([[]|FS]):-instanciar(FS).
instanciar([[C|CS]|FS]):-valor(C), instanciar([CS|FS]).
%Usamos la estrategía Generate & test, Instanciamos el tablero con "lo que sea" y verificamos  si es consistente.













%Toma 2
%Ejercicio 10
%completarB(?T) donde se intentara mejorar el recorrido del espacio de busqueda. La motivacion es hacer una verificacion de consistencia por celda lo antes que se pueda.
%Por ejemplo, una vez determinado un valor para la celda en la posicion C, F se puede verificar la consistencia de la celda C-1, F-1;
%adicionalmente si C, F es un borde derecho o inferior, se puede verificar consistencia en otras celdas.
%De forma similar al caso anterior, se puede ver el tiempo de la primera solucion de la siguiente manera:
%rB(N,T) :− pre r(N,T) , completarB(T) , post r(T).
%?- rB(t1 ,T).
%date(2011, 5, 23, 13, 33, 19.9863, 0, UTC, −)
%∗1
%11
%date(2011, 5, 23, 13, 33, 19.9959, 0, UTC, −)
%T = [[mina,1], [1,1]].
%completarB()

%valor(+T,+C,+F,?E) devuelve o chequea el valor de una celda
valor(T,C,F,E):- index(T,F,FF), index(FF,C,E).
%posiciones(+T,-PS) devuelve una lista con las posiciones dentro del tablero
posiciones(T,PS):-setof(p(C,F),pos(T,C,F),PS).
%posicionesVal(+T,-PS) devuelve una lista de p(C,F,E) que es cada posicion del tablero junto con su valor
posicionesVal(T,PS):-setof(p(C,F,E),posVal(T,C,F,E),PS).
%posVal(+T,?C,?F,?E) vale si C,F es una posicion del tablero y E es su valor (o enlista todos las posiciones con sus valores)
posVal(T,C,F,E):-pos(T,C,F),valor(T,C,F,E).

completarB(T):- posicionesVal(T,PS), llenarB(T,PS), consistente(T).
%en este caso, chequea la consistencia de las celdan en cuanto puede, para no seguir explorando una rama del arbol que ya contiene una insconsistencia
llenarB(_,[]):-!.
llenarB(T,[p(C,F,E)|PS]):-dim(T,C,_),                       valor(E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), consistente(T,C,Fm1), llenarB(T,PS).
llenarB(T,[p(C,F,E)|PS]):-not(dim(T,C,_)), dim(T,_,F),      valor(E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), consistente(T,Cm1,F), llenarB(T,PS).
llenarB(T,[p(C,F,E)|PS]):-not(dim(T,C,_)), not(dim(T,_,F)), valor(E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), llenarB(T,PS).
% Chequeamos la consistencia, como sugieren de el elemento de "arriba a la izquierda" salvo los bordes que son tratados especialmente
% En general, chequeamos la consistencia de cada celda apenas esten instanciados todos sus vecinos
% (por ejemplo, cuando se instancia un elemento del borde derecho del tablero, se chequea la consistencia de la posicion de arriba y la de arriba a la izquiera porque ya tienen todos los vecinos instanciados)
% Para no dar casos repetidos, procuramos usar casos excluyentes.












%Toma 3
%Ejercicio 11
%completarC(?T) donde nuevamente se intentar ́ mejorar el recorrido del espacio de búsqueda. 
%Esta vez la motivación radica en no probar con todos los valores: mina, 0, . . ., 8 para cada
%celda. Se debe usar la información de los vecinos para reducir los posibles valores. Por ejemplo:
%Si un vecino instanciado vale 0 entonces se sabe que la celda central no puede tener una mina.
%La cantidad de minas en los vecinos está acotada por los vecinos que ya estan instanciados en mina 
%y adicionalmente cuántos vecinos aún no están instanciados.

completarC(T):-posicionesVal(T,PS), llenarC(T,PS), consistente(T).
%toma la lista de posiciones y valores del tablero, luego instancia las variables y por ultimo chequea consistencia

%para cada posicion, la instancia en (o verifica que sea) un valor posible, y luego chequea la consistencia de las posiciones que quedaron con los vecinos instanciados
llenarC(_,[]):-!.
llenarC(T,[p(C,F,E)|PS]):-dim(T,C,_),                       vecinos(T,C,F,VS), valoresPosibles(VS,E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), consistente(T,C,Fm1), llenarC(T,PS).
llenarC(T,[p(C,F,E)|PS]):-not(dim(T,C,_)), dim(T,_,F),      vecinos(T,C,F,VS), valoresPosibles(VS,E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), consistente(T,Cm1,F), llenarC(T,PS).
llenarC(T,[p(C,F,E)|PS]):-not(dim(T,C,_)), not(dim(T,_,F)), vecinos(T,C,F,VS), valoresPosibles(VS,E), Cm1 is C-1, Fm1 is F-1, consistente(T,Cm1,Fm1), llenarC(T,PS).

%min(+L,-Res)
min(XS,Min):-min2(XS,_,Min).
min2([],E,E):- !.
min2([X|XS],M,R) :- var(M), min2(XS,X,R), !.
min2([X|XS],M,R) :- X<M   , min2(XS,X,R).
min2([X|XS],M,R) :- X>=M  , min2(XS,M,R).

%max(+L,-Res)
max(XS,Max):-max2(XS,_,Max).
max2([],E,E):- !.
max2([X|XS],M,R) :- var(M), max2(XS,X,R), !.
max2([X|XS],M,R) :- X>M   , max2(XS,X,R).
max2([X|XS],M,R) :- X=<M  , max2(XS,M,R).

%vars(+L,-CantVars), cuenta la cantidad de elementos no instanciados
vars([],0):- !.
vars([E|ES],C):-var(E), vars(ES,Cm1), C is Cm1+1, !.
vars([E|ES],C):-nonvar(E), vars(ES,C).

%Como propone el enunciado, los valores posibles para una posicion son:
%mina, si no hay un 0 entre los vecinos
%un numero que esta entre la cantidad de minas y la cantidad de minas+cantidad de variables (potenciales minas) entre los vecinos
valoresPosibles(VS,VP):- nonvars(VS,VSI), not(member(0,VSI)), VP=mina.
valoresPosibles(VS,VP):- cant_minas(VS,Minas), vars(VS,CantVars), Max is CantVars+Minas, between(Minas,Max,VP).

%Resultados
%Ejercicio 12
%Incluir en el informe una tabla con los tiempos insumidos, para cada una de las tres
%alternativas, en encotrar una soluci ́n (la primera). Es posible que algunos problemas requieran mucho tiempo. Pueden decidir un tiempo de corte.

%Toma 4 (opcional)
%Ejercicio 13
%Se invita a pensar una cuarta variante de completar e incluir sus resultados en la tabla del punto anterior.


%La idea es primero colocar las minas de tal forma de que quede "consistente", y luego los valores numericos quedan determinados por la cantidad de minas en sus vecinos.
%Es mucho mas eficiente porque solo prueba con 2 valores: mina y "num"
%Adicionalmente, prueba con una mina solo si no rompe la consistencia de ningun vecino
completar(T):-copiar(T,T2),ponerMinas(T2),ponerNum(T2,T),consistente(T).
%copiar hace una copia del tablero,
%ponerMinas pone minas o "num" de manera consistente en las posiciones candidatas,
%ponerNum reemplaza los "num" y las variables por el numero correspondiente.
%por ultimo se chequea la consistencia, aunque no es necesario porque ponerMinas y ponerNum deberian dejar un tablero consistente

ponerMinas(T):-posCandidatas(T,PC), ponerMinas(T,PC).
%las posiciones candidatas a tener una mina son las que tienen almenos un numero (positivo) como vecino.
posCandidatas(T,PC):-posicionesVal(T,PS), filtrarCandidatas(T,PS,PC).
filtrarCandidatas(_,[]    ,[]):-!.
filtrarCandidatas(T,[p(C,F,E)|PS],[p(C,F)|PC]):-var(E), vecinos(T,C,F,VS), hayNum(VS), filtrarCandidatas(T,PS,PC), !.
filtrarCandidatas(T,[_|PS],PC):- filtrarCandidatas(T,PS,PC).
ponerMinas(_,[]).
%cada posicion candidata puede ser una mina (si todos los vecinos numericos no estan saturados, y se mantiene la consistencia), o un "num"
ponerMinas(T,[p(C,F)|PC]):-not(vecinoNumericoSat(T,C,F)),valor(T,C,F,E),E=mina,vecinosConsistentes(T,C,F),ponerMinas(T,PC).
ponerMinas(T,[p(C,F)|PC]):-valor(T,C,F,E),E=num,vecinosConsistentes(T,C,F),ponerMinas(T,PC).
%enlista los vecinos numericos que estan saturados
vecinoNumericoSat(T,C,F):-posVecina(T,C,F,p(CV,FV)),valor(T,CV,FV,E),numerico(E),saturado(T,CV,FV,E).
%vale si una posicion p(CV,FV) es vecina de la posicion C,F 
posVecina(T,C,F,p(CV,FV)):- Cm1 is C-1,Fm1 is F-1,CM1 is C+1,FM1 is F+1,between(Cm1,CM1,CV),between(Fm1,FM1,FV),pos(T,CV,FV),not(yo(C,F,CV,FV)).
%funcion identidad de las posiciones
yo(C,F,C,F).
%una posicion numerica esta saturada si la cantidad de minas en sus vecinos es mayor o igual al valor
saturado(T,C,F,E):-not(E=num),vecinos(T,C,F,VS),cant_minas(VS,Minas), Minas>=E.
%una posicion es numerica si esta instanciada y no es una mina
numerico(E):-nonvar(E),not(mina(E)).
%verdadero si alguno de los elementos de la lista es numerico
hayNum([V|_ ]):-numerico(V),V>0,!.
hayNum([_|VS]):-hayNum(VS).
%chequea consistencia sobre todos los vecinos
vecinosConsistentes(T,C,F):-setof(p(CV,FV),posVecina(T,C,F,p(CV,FV)),PVS),sonConsist(T,PVS).
sonConsist(_,[]          ):-!.
sonConsist(T,[p(C,F)|PVS]):-esConsistente(T,C,F), sonConsist(T,PVS).
esConsistente(T,C,F) :- vecinosyYo(T,C,F,VS,E), esConsistente2(VS,E), !.
esConsistente2(_,E):- var(E), !.
esConsistente2(_,E):- nonvar(E),E=mina, !.
esConsistente2(_,E):- nonvar(E),E=num , !.
esConsistente2(VS,E) :- valoresPosibles(VS,E), !.
%copia un tablero genrando uno exactamente igual (con distintas variables libres)
copiar([]         ,[]            ):- !.
copiar([[]|FS]    ,[[]|FS2]      ):- copiar(FS,FS2), !.
copiar([[E|ES]|FS],[[_ |ES2]|FS2]):- var(E), copiar([ES|FS],[ES2|FS2]), !.
copiar([[E|ES]|FS],[[E |ES2]|FS2]):- copiar([ES|FS],[ES2|FS2]), !.
%copia un tablero a otro mientras cambia los "num" y las variables libres por el valor adecuado
ponerNum(T2,T):-posicionesVal(T2,PT2), ponerNum(T2,T,PT2).
ponerNum(_,_,[]):-!.
ponerNum(T2,T,[p(C,F,E2)|PS]):- E2=num, vecinos(T2,C,F,VS), cant_minas(VS,Minas), valor(T,C,F,E), E=Minas, ponerNum(T2,T,PS), !.
ponerNum(T2,T,[p(C,F,E2)|PS]):- valor(T,C,F,E), E=E2, ponerNum(T2,T,PS), !.





%FUNCIONES PARA PROBAR Y EJEcUTAR

pre_r(N,T) :- get_time(T1), stamp_date_time(T1, X1, 'UTC'), write(X1), nl, problem(N,T).
post_r(T) :- mostrar(T), get_time(T2), stamp_date_time(T2, X2, 'UTC'), write(X2), nl.

rA(N,T) :- pre_r(N,T), completarA(T), post_r(T).
rB(N,T) :- pre_r(N,T), completarB(T), post_r(T).
rC(N,T) :- pre_r(N,T), completarC(T), post_r(T).
r(N,T)  :- pre_r(N,T), completar(T) , post_r(T).
	
mostrar([]).
mostrar([Fila|T]) :-
	mostrar_lista(Fila),
	mostrar(T).

mostrar_lista([]) :- nl.
mostrar_lista([H|T]) :- mostrar_celda(H), mostrar_lista(T).

mostrar_celda(C) :- nonvar(C), C == mina, write('*').
mostrar_celda(C) :- nonvar(C), C\=mina, C==num, write('-').
mostrar_celda(C) :- nonvar(C), C\=mina, C\=num, write(C).
mostrar_celda(C) :- var(C), write('_').

problem(t1, [[_,_],
			 [_,1]]).

problem(t2, [[_,_],
			 [_,2]]).

problem(t3, [[_,_],
			 [_,3]]).

problem(t4, [[0,_,_],
			 [_,1,_],
			 [_,_,0]]).
% Problem from Gecode/examples/minesweeper.cc  problem 0
% 
% Solution:
%  1 0 0 0 0 1
%  0 1 0 1 1 0
%  0 0 0 0 1 0
%  0 0 0 0 1 0
%  0 1 1 1 0 0
%  1 0 0 0 1 1
%
problem(0,[[_,_,2,_,3,_],
           [2,_,_,_,_,_],
           [_,_,2,4,_,3],
           [1,_,3,4,_,_],
           [_,_,_,_,_,3],
           [_,3,_,3,_,_]]).


% Problem from Gecode/examples/minesweeper.cc  problem 1
problem(1,[[_,2,_,2,1,1,_,_],
           [_,_,4,_,2,_,_,2],
           [2,_,_,2,_,_,3,_],
           [2,_,2,2,_,3,_,3],
           [_,_,1,_,_,_,4,_],
           [1,_,_,_,2,_,_,3],
           [_,2,_,2,2,_,3,_],
           [1,_,1,_,_,1,_,1]]).



% Problem from Gecode/examples/minesweeper.cc  problem 2
problem(2,[[1,_,_,2,_,2,_,2,_,_],
           [_,3,2,_,_,_,4,_,_,1],
           [_,_,_,1,3,_,_,_,4,_],
           [3,_,1,_,_,_,3,_,_,_],
           [_,2,1,_,1,_,_,3,_,2],
           [_,3,_,2,_,_,2,_,1,_],
           [2,_,_,3,2,_,_,2,_,_],
           [_,3,_,_,_,3,2,_,_,3],
           [_,_,3,_,3,3,_,_,_,_],
           [_,2,_,2,_,_,_,2,2,_]]).


% Problem from Gecode/examples/minesweeper.cc  problem 3
problem(3,[[2,_,_,_,3,_,1,_],
           [_,5,_,4,_,_,_,1],
           [_,_,5,_,_,4,_,_],
           [2,_,_,_,4,_,5,_],
           [_,2,_,4,_,_,_,2],
           [_,_,5,_,_,4,_,_],
           [2,_,_,_,5,_,4,_],
           [_,3,_,3,_,_,_,2]]).


% Problem from Gecode/examples/minesweeper.cc  problem 4
problem(4,[[0,_,0,_,1,_,_,1,1,_],
           [1,_,2,_,2,_,2,2,_,_],
           [_,_,_,_,_,_,2,_,_,2],
           [_,2,3,_,1,1,_,_,_,_],
           [0,_,_,_,_,_,_,2,_,1],
           [_,_,_,2,2,_,1,_,_,_],
           [_,_,_,_,_,3,_,3,2,_],
           [_,5,_,2,_,_,_,3,_,1],
           [_,3,_,1,_,_,3,_,_,_],
           [_,2,_,_,_,1,2,_,_,0]]).


% Problem from Gecode/examples/minesweeper.cc  problem 5
problem(5,[[_,2,1,_,2,_,2,_,_,_],
           [_,4,_,_,3,_,_,_,5,3],
           [_,_,_,4,_,4,4,_,_,3],
           [4,_,4,_,_,5,_,6,_,_],
           [_,_,4,5,_,_,_,_,5,4],
           [3,4,_,_,_,_,5,5,_,_],
           [_,_,4,_,4,_,_,5,_,5],
           [2,_,_,3,3,_,6,_,_,_],
           [3,6,_,_,_,3,_,_,4,_],
           [_,_,_,4,_,2,_,2,1,_]]).



% Problem from Gecode/examples/minesweeper.cc  problem 6
problem(6,[[_,3,2,_,_,1,_,_],
           [_,_,_,_,1,_,_,3],
           [3,_,_,2,_,_,_,4],
           [_,5,_,_,_,5,_,_],
           [_,_,6,_,_,_,5,_],
           [3,_,_,_,5,_,_,4],
           [2,_,_,5,_,_,_,_],
           [_,_,2,_,_,3,4,_]]).


% Problem from Gecode/examples/minesweeper.cc  problem 7
problem(7,[[_,1,_,_,_,_,_,3,_],
           [_,_,_,3,4,3,_,_,_],
           [2,4,4,_,_,_,4,4,3],
           [_,_,_,4,_,4,_,_,_],
           [_,4,_,4,_,3,_,6,_],
           [_,_,_,4,_,3,_,_,_],
           [1,2,3,_,_,_,1,3,3],
           [_,_,_,3,2,2,_,_,_],
           [_,2,_,_,_,_,_,3,_]]).



% Problem from Gecode/examples/minesweeper.cc  problem 8
problem(8,[[_,_,_,_,_,_,_],
           [_,2,3,4,3,5,_],
           [_,1,_,_,_,3,_],
           [_,_,_,5,_,_,_],
           [_,1,_,_,_,3,_],
           [_,1,2,2,3,4,_],
           [_,_,_,_,_,_,_]]).


% Problem from Gecode/examples/minesweeper.cc  problem 9
problem(9,[[2,_,_,_,2,_,_,_,2],
           [_,4,_,4,_,3,_,4,_],
           [_,_,4,_,_,_,1,_,_],
           [_,4,_,3,_,3,_,4,_],
           [2,_,_,_,_,_,_,_,2],
           [_,5,_,4,_,5,_,4,_],
           [_,_,3,_,_,_,3,_,_],
           [_,4,_,3,_,5,_,6,_],
           [2,_,_,_,1,_,_,_,2]]).



% From "Some Minesweeper Configurations",page 2
problem(10,[[_,_,_,_,_,_],
            [_,2,2,2,2,_],
            [_,2,0,0,2,_],
            [_,2,0,0,2,_],
            [_,2,2,2,2,_],
            [_,_,_,_,_,_]]).



% From "Some Minesweeper Configurations",page 3
% 4 solutions
problem(11,[[2,3,_,2,2,_,2,1],
            [_,_,4,_,_,4,_,2],
            [_,_,_,_,_,_,4,_],
            [_,5,_,6,_,_,_,2],
            [2,_,_,_,5,5,_,2],
            [1,3,4,_,_,_,4,_],
            [0,1,_,4,_,_,_,3],
            [0,1,2,_,2,3,_,2]]).


% Richard Kaye: How Complicated is Minesweeper?
% http://web.mat.bham.ac.uk/R.W.Kaye/minesw/ASE2003.pdf
% 
% A Wire,page 33
% 2 solutions
%
problem(12,[[_,0,0,0,0,0,0,0,0,0,0,0,0,_],
            [_,1,1,1,1,1,1,1,1,1,1,1,1,_],
            [_,_,1,_,_,1,_,_,1,_,_,1,_,_],
            [_,1,1,1,1,1,1,1,1,1,1,1,1,_],
            [_,0,0,0,0,0,0,0,0,0,0,0,0,_]]).


% Richard Kaye: How Complicated is Minesweeper?
% http://web.mat.bham.ac.uk/R.W.Kaye/minesw/ASE2003.pdf
% A splitter,page 35
% Many solutions...
%
problem(13,[[_,_,_,0,_,_,_,0,_,_,_],
            [_,_,_,0,1,_,1,0,_,_,_],
            [_,_,_,0,1,_,1,0,_,_,_],
            [0,0,0,0,1,1,1,0,0,0,0],
            [_,1,1,1,1,_,1,1,1,1,_],
            [_,_,_,1,_,2,_,1,_,_,_],
            [_,1,1,1,1,_,1,1,1,1,_],
            [0,0,0,0,1,1,1,0,0,0,0],
            [_,_,_,0,1,_,1,0,_,_,_],
            [_,_,_,0,1,_,1,0,_,_,_],
            [_,_,_,0,_,_,_,0,_,_,_]]).
        


% Oleg German,Evgeny Lakshtanov: "Minesweeper" without a computer
% http://arxiv.org/abs/0806.3480,page 4
problem(14,[[_,1,_,1,_,1],
            [2,_,2,_,1,_],
            [_,3,_,2,_,1],
            [1,_,3,_,2,_],
            [_,1,_,2,_,1]]).
